#include <stdio.h>

void io_hlt(void);
void io_cli(void);
int io_in8(int port);
int io_in16(int port);
int io_in32(int port);
void io_out8(int port,int data);
void io_out16(int port,int data);
void io_out32(int port,int data);
int io_load_eflags(void);
void io_store_eflags(int eflags);

void init_palette(void);
void set_palette(int start,int end,unsigned char *rgb);
void boxfill8(unsigned char *vram, int xsize, unsigned char c, int x0, int y0, int x1, int y1);
void init_screen(char *vram,int xsize,int ysize);
void putfont8(char *vram,int xsize,int x,int y,char c,char *font);
void putfonts8_asc(char *vram,int xsize,int x,int y,char c,unsigned char *s);

#define COL8_000000		0
#define COL8_FF0000		1
#define COL8_00FF00		2
#define COL8_FFFF00		3
#define COL8_0000FF		4
#define COL8_FF00FF		5
#define COL8_00FFFF		6
#define COL8_FFFFFF		7
#define COL8_C6C6C6		8
#define COL8_840000		9
#define COL8_008400		10
#define COL8_848400		11
#define COL8_000084		12
#define COL8_840084		13
#define COL8_008484		14
#define COL8_848484		15

struct BOOTINFO
{
	char cyls,leds,vmode,reserve;
	short scrnx,scrny;
	char *vram;
};

void EMMain(void)
{
	//static char font_A[16] = {
	//	0x00, 0x18, 0x18, 0x18, 0x18, 0x24, 0x24, 0x24,
	//	0x24, 0x7e, 0x42, 0x42, 0x42, 0xe7, 0x00, 0x00
	//};
	
	struct BOOTINFO *binfo=(struct BOOTINFO *)0x0ff0;
	extern char hankaku[4096];
	
	init_palette();
	
	init_screen(binfo->vram,binfo->scrnx,binfo->scrny);

	putfonts8_asc(binfo->vram,binfo->scrnx,31,31,COL8_000000,"Hello,EMOS");
	
	for(;;)
	{
		io_hlt();
	}
}

void init_palette(void)
{
	static unsigned char table_rgb[16*3]={
		0x00, 0x00, 0x00,	/*  0:黑 */
		0xff, 0x00, 0x00,	/*  1:亮红*/
		0x00, 0xff, 0x00,	/*  2:亮绿*/
		0xff, 0xff, 0x00,	/*  3:亮黄*/
		0x00, 0x00, 0xff,	/*  4:亮蓝*/
		0xff, 0x00, 0xff,	/*  5:亮紫*/
		0x00, 0xff, 0xff,	/*  6:浅亮蓝*/
		0xff, 0xff, 0xff,	/*  7:白*/
		0xc6, 0xc6, 0xc6,	/*  8:亮灰*/
		0x84, 0x00, 0x00,	/*  9:暗红*/
		0x00, 0x84, 0x00,	/* 10:暗绿*/
		0x84, 0x84, 0x00,	/* 11:暗黄*/
		0x00, 0x00, 0x84,	/* 12:暗青*/
		0x84, 0x00, 0x84,	/* 13:暗紫*/
		0x00, 0x84, 0x84,	/* 14:浅暗蓝*/
		0x84, 0x84, 0x84	/* 15:暗灰*/
	};
	set_palette(0,15,table_rgb);
}

void set_palette(int start,int end,unsigned char *rgb)
{
	int i,eflags;
	eflags=io_load_eflags();
	io_cli();
	io_out8(0x3c8,start);
	for(i=start;i<=end;i++)
	{
		io_out8(0x3c9,rgb[0]/4);
		io_out8(0x3c9,rgb[1]/4);
		io_out8(0x3c9,rgb[2]/4);
		rgb+=3;
	}
	io_store_eflags(eflags);
}

void boxfill8(unsigned char *vram,int xsize,unsigned char c,int x0,int y0,int x1,int y1)
{
	int x,y;
	for(y=y0;y<=y1;y++)
	{
		for(x=x0;x<=x1;x++)
		{
			vram[y*xsize+x]=c;
		}
	}
}

void init_screen(char *vram,int xsize,int ysize)
{
	//画矩形
	boxfill8(vram, xsize, COL8_848484,  0,  0, xsize-1, ysize-1);
}

void putfont8(char *vram,int xsize,int x,int y,char c,char *font)//显示字符
{
	int i;
	char *p,d;
	for(i=0;i<16;i++)//根据font设置第i行像素值,共有16行
	{
		p=vram+(y+i)*xsize+x;
		d=font[i];
		
		//获取所在行相应位
		if((d&0x80)!=0){p[0]=c;}//10000000
		if((d&0x40)!=0){p[1]=c;}//01000000
		if((d&0x20)!=0){p[2]=c;}//00100000
		if((d&0x10)!=0){p[3]=c;}//00010000
		if((d&0x08)!=0){p[4]=c;}//00001000
		if((d&0x04)!=0){p[5]=c;}//00000100
		if((d&0x02)!=0){p[6]=c;}//00000010
		if((d&0x01)!=0){p[7]=c;}//00000001
	}
}

void putfonts8_asc(char *vram,int xsize,int x,int y,char c,unsigned char *s)
{
	extern char hankaku[4096];
	for(;*s!=0x00;s++)
	{
		putfont8(vram,xsize,x,y,c,hankaku+*s*16);
		x+=8;
	}
}